Google Calendarの予定が始まる15分前にGoogle Homeから音声でリマインドを送る(2020年版)
クラスメソッドに入社以降 Google Calendar でのスケジュール共有が頻繁に行われている一方、在宅勤務により Google Home を活用する機会も多いので、何とか予定を目の前の Google Home mini から通知出来ないか調べたところ、稲葉さんのブログが見つかりました。
Google Calendarの予定が始まる15分前にGoogle Homeから音声でリマインドを送る
Developers.IO 何でもあるな…と驚きつつ試してみたところ、状況の変化によりそのままでは動作しないところがありましたので、2020年版の差分として共有します。
前提条件
- Google Homeをセットアップ済みであること
- Google Homeと同じLAN内にNode.jsが実行できるサーバがあること(所持している無印 Raspberry Pi には荷が重かったので、LANに繋がっている格安サーバを使用)
動作環境
- Node.js:v12.16.3 (執筆時点のLTS)
- npm:6.14.4
- OS:CentOS 7.8.2003 (Core)
構成
オリジナルブログと同様のため省略。
やってみる
google-home-notifier が動かない
オリジナルの手順通り、Goole Home mini の IPアドレスを調べ、example.js を修正して実行しても動きません。
まず、ngrok によって自動生成される URL の FQDN が undefined
となっています。
$ node example.js *** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi. *** WARNING *** Please fix your application to use the native API of Avahi! *** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node> *** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi. *** WARNING *** Please fix your application to use the native API of Avahi! *** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister> Endpoints: http://192.168.1.XXX:8091/google-home-notifier undefined/google-home-notifier GET example: curl -X GET undefined/google-home-notifier?text=Hello+Google+Home POST example: curl -X POST -d "text=Hello Google Home" undefined/google-home-notifier
とりあえずLANで、と example.js 実行マシンに対して curl を実行すると今度は以下のエラーとなります。
{ text: 'Hello Google Home' } Error: get key failed from google at /home/XXXXX/google-home-notifier/node_modules/google-tts-api/lib/key.js:27:13 at processTicksAndRejections (internal/process/task_queues.js:97:5)
ngrokの挙動を修正する
example.js を調べたところ、以下の箇所でエラーが発生し url
が取得出来ていません。
ngrok.connect(serverPort, function (err, url) {
Error: ngrok is not yet ready to start tunnels at Request._callback (/home/XXXXX/google-home-notifier/node_modules/ngrok/index.js:192:30) at Request.self.callback (/home/XXXXX/google-home-notifier/node_modules/request/request.js:185:22) at Request.emit (events.js:310:20) at Request.<anonymous> (/home/XXXXX/google-home-notifier/node_modules/request/request.js:1154:10) at Request.emit (events.js:310:20) at IncomingMessage.<anonymous> (/home/XXXXX/google-home-notifier/node_modules/request/request.js:1076:12) at Object.onceWrapper (events.js:416:28) at IncomingMessage.emit (events.js:322:22) at endReadableNT (_stream_readable.js:1187:12) at processTicksAndRejections (internal/process/task_queues.js:84:21) { error_code: 104, status_code: 503, msg: 'ngrok is not yet ready to start tunnels', details: { err: 'a successful ngrok tunnel session has not yet been established' } }
どうしたもんかと思ったのですが、インストールされる ngrok のバージョンが 2.3.0
と古く、現在の ngrok は async/await に対応しているようなので、試しに package.json
の ngrok を 3.2.7
に書き換えて、example.js
を以下のように修正したところ、無事 url が取れるようになりました。
@@ -95,8 +95,8 @@ app.get('/google-home-notifier', function (req, res) { } }) -app.listen(serverPort, function () { - ngrok.connect(serverPort, function (err, url) { +app.listen(serverPort, async function () { + const url = await ngrok.connect(serverPort); console.log('Endpoints:'); console.log(' http://' + ip + ':' + serverPort + '/google-home-notifier'); console.log(' ' + url + '/google-home-notifier'); @@ -104,5 +104,4 @@ app.listen(serverPort, function () { console.log('curl -X GET ' + url + '/google-home-notifier?text=Hello+Google+Home'); console.log('POST example:'); console.log('curl -X POST -d "text=Hello Google Home" ' + url + '/google-home-notifier'); - }); })
$ npm update ngrok $ node example.js *** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi. *** WARNING *** Please fix your application to use the native API of Avahi! *** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node> *** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi. *** WARNING *** Please fix your application to use the native API of Avahi! *** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister> Endpoints: http://192.168.1.XXX:8091/google-home-notifier https://取得したサブドメイン.ngrok.io/google-home-notifier GET example: curl -X GET https://取得したサブドメイン.ngrok.io/google-home-notifier?text=Hello+Google+Home POST example: curl -X POST -d "text=Hello Google Home" https://取得したサブドメイン.ngrok.io/google-home-notifier
Error: get key failed from google 問題を解決する
検索すると色々情報が出てきますが、現時点だと package.json
の google-tts-api を 0.0.4
に書き換えれば良いようです。
Error: get key failed from google in version 0.0.3 · Issue #22 · zlargon/google-tts
$ npm update google-tts-api $ curl -X GET http://localhost:8091/google-home-notifier?text=Hello+Google+Home Google Home will say: Hello Google Home
サーバの用意
ここからは、基本的にオリジナルブログ通りで大丈夫です。
おそらくオリジナルブログを書かれた時点ではそのような仕様では無かったのだと思いますが、現時点だと作成したセッションは8時間で期限切れとなるようです。
いつの間にかアカウント登録無しでのngrok利用にセッション時間制限が設定されてた。 - ダンデライオン
google-home-notifierが気づいたら動かなくなってた時の対処法 - Qiita
ずっと動かし続ける必要があるサービスなので、事実上 Authtoken の取得が必須(ngrok へのアカウント登録が必要)となっています。
IFTTTの設定
IFTTT の画面は結構変わっていますが、設定内容は同じです。
最終的な差分
diff --git a/example.js b/example.js index 43454e6..aa9e803 100644 --- a/example.js +++ b/example.js @@ -4,9 +4,12 @@ var ngrok = require('ngrok'); var bodyParser = require('body-parser'); var app = express(); const serverPort = 8091; // default port +const token = '取得したngrokのトークン'; +const user = 'Basic認証ユーザ名'; +const password = 'Basic認証パスワード'; var deviceName = 'Google Home'; -var ip = '192.168.1.20'; // default IP +var ip = 'Google Home mini のIP'; // default IP var urlencodedParser = bodyParser.urlencoded({ extended: false }); @@ -21,7 +24,7 @@ app.post('/google-home-notifier', urlencodedParser, function (req, res) { ip = req.query.ip; } - var language = 'pl'; // default language code + var language = 'ja'; // default language code if (req.query.language) { language; } @@ -63,7 +66,7 @@ app.get('/google-home-notifier', function (req, res) { ip = req.query.ip; } - var language = 'pl'; // default language code + var language = 'ja'; // default language code if (req.query.language) { language; } @@ -95,14 +98,13 @@ app.get('/google-home-notifier', function (req, res) { } }) -app.listen(serverPort, function () { - ngrok.connect(serverPort, function (err, url) { - console.log('Endpoints:'); - console.log(' http://' + ip + ':' + serverPort + '/google-home-notifier'); - console.log(' ' + url + '/google-home-notifier'); - console.log('GET example:'); - console.log('curl -X GET ' + url + '/google-home-notifier?text=Hello+Google+Home'); +app.listen(serverPort, async function () { + const url = await ngrok.connect({authtoken: token, addr: serverPort, auth: user + ":" + password}); + console.log('Endpoints:'); + console.log(' http://' + ip + ':' + serverPort + '/google-home-notifier'); + console.log(' ' + url + '/google-home-notifier'); + console.log('GET example:'); + console.log('curl -X GET ' + url + '/google-home-notifier?text=Hello+Google+Home'); console.log('POST example:'); console.log('curl -X POST -d "text=Hello Google Home" ' + url + '/google-home-notifier'); - }); }) diff --git a/package.json b/package.json index 4bb710e..651df71 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,8 @@ "body-parser": "^1.15.2", "castv2-client": "^1.1.2", "express": "^4.14.0", - "google-tts-api": "0.0.2", + "google-tts-api": "0.0.4", "mdns": "^2.3.3", - "ngrok": "^2.2.4" + "ngrok": "^3.2.7" } }
まとめ
作業に集中している時にも予定を知らせてくれるようになって、便利になりました。
google-home-notifier の更新が2年前から止まっているため、今後どこまで利用出来るのかという不安が無いわけではないですが、代替のものを探してくるのも難しそうなので、末永く動作して欲しいと思います。